#include "dht11_eswin.h"
#include "pins_driver.h"


#define DHT11_DQ_LOW()                                                            \
    do {                                                                          \
        PINS_DRV_WritePinDirection(DHT11_PORT, DHT11_PIN, GPIO_OUTPUT_DIRECTION); \
        PINS_DRV_WritePin(DHT11_PORT, DHT11_PIN, 0);                              \
    } while (0)

#define DHT11_DQ_HIGH()                                                          \
    do {                                                                         \
        PINS_DRV_WritePin(DHT11_PORT, DHT11_PIN, 1);                             \
        PINS_DRV_WritePinDirection(DHT11_PORT, DHT11_PIN, GPIO_INPUT_DIRECTION); \
    } while (0)

#define DHT11_DQ_READ() ((PINS_DRV_ReadPins(DHT11_PORT) >> DHT11_PIN) & 0x01)

// 复位DHT11
static void DHT11_Rst(void)
{
    DHT11_DQ_LOW();    // 拉低DQ
    OS_DelayUs(18000); // 拉低至少18ms
    DHT11_DQ_HIGH();   // 释放总线
    OS_DelayUs(30);    // 主机拉高20~40us
}

// 等待DHT11的回应
// 返回0:存在, 非0:不存在
static dht11_error_t DHT11_Check(void)
{
    uint32_t retry = 0;

    // 等待DHT11拉低总线40~80us
    while (DHT11_DQ_READ() && retry < 100) {
        retry++;
        OS_DelayUs(1);
    }

    if (retry >= 100)
        return DHT11_ERROR_NO_RESPONSE;

    retry = 0;

    // 等待DHT11释放总线40~80us
    while (!DHT11_DQ_READ() && retry < 100) {
        retry++;
        OS_DelayUs(1);
    }

    if (retry >= 100)
        return DHT11_ERROR_TIMEOUT;

    return DHT11_OK;
}

// 从DHT11读取一个位
static uint8_t DHT11_Read_Bit(void)
{
    uint32_t retry = 0;

    // 等待低电平开始
    while (DHT11_DQ_READ() && retry < 100) {
        retry++;
        OS_DelayUs(1);
    }

    retry = 0;

    // 等待高电平开始
    while (!DHT11_DQ_READ() && retry < 100) {
        retry++;
        OS_DelayUs(1);
    }

    OS_DelayUs(40); // 等待40us

    return DHT11_DQ_READ() ? 1 : 0;
}

// 从DHT11读取一个字节
static uint8_t DHT11_Read_Byte(void)
{
    uint8_t dat = 0;

    for (int i = 0; i < 8; i++) {
        dat <<= 1;
        dat |= DHT11_Read_Bit();
    }

    return dat;
}

status_t DHT11_Init(void)
{
    // 配置引脚为开漏输出模式（需要外部上拉电阻）
    PINS_DRV_SetMuxModeSel(DHT11_PORT, DHT11_PIN, PORT_MUX_ALT1);
    PINS_DRV_SetPullSel(DHT11_PORT, DHT11_PIN, PORT_INTERNAL_PULL_NOT_ENABLED);
    DHT11_DQ_HIGH();

    // 测试传感器响应
    dht11_data_t dummy;
    return (DHT11_Read_Data(&dummy) == DHT11_OK) ? STATUS_SUCCESS : STATUS_ERROR;
}

dht11_error_t DHT11_Read_Data(dht11_data_t *data)
{
    if (data == NULL)
        return DHT11_ERROR_CHECKSUM;

    // 复位传感器
    DHT11_Rst();

    // 检查响应
    dht11_error_t err = DHT11_Check();
    if (err != DHT11_OK)
        return err;

    // 读取40位数据
    uint8_t buf[5] = {0};
    for (int i = 0; i < 5; i++) {
        buf[i] = DHT11_Read_Byte();
    }

    // 校验和验证
    if ((buf[0] + buf[1] + buf[2] + buf[3]) != buf[4]) {
        return DHT11_ERROR_CHECKSUM;
    }

    // 填充数据
    data->humidity_integer    = buf[0];
    data->humidity_decimal    = buf[1];
    data->temperature_integer = buf[2];
    data->temperature_decimal = buf[3];

    return DHT11_OK;
}
